package com.googlecode.stockhamster.company;

import java.net.MalformedURLException;

import com.googlecode.stockhamster.Constant;
import com.googlecode.stockhamster.bank.IBank;
import com.googlecode.stockhamster.expert.IExpert;
import com.googlecode.stockhamster.rumor.IRumor;
import com.googlecode.stockhamster.stockmarket.IStockMarket;
import com.googlecode.stockhamster.stockstat.IStockStat;
import com.googlecode.stockhamster.utils.XFireStub;

public class CompanyServiceImpl implements ICompany {

	private IBank bank;
	private IStockMarket stockMarket;
	private IStockStat status;
	private IRumor rumor;
	private IExpert expert;

	public CompanyServiceImpl() throws MalformedURLException {
		bank = new XFireStub<IBank>(Constant.bankUrl, IBank.class).getStub();
		stockMarket = new XFireStub<IStockMarket>(Constant.stockMarketUrl,
				IStockMarket.class).getStub();
		status = new XFireStub<IStockStat>(Constant.stockStatUrl,
				IStockStat.class).getStub();
		rumor = new XFireStub<IRumor>(Constant.rumorUrl, IRumor.class)
				.getStub();
		expert = new XFireStub<IExpert>(Constant.expertUrl, IExpert.class)
				.getStub();
	}

	@Override
	public Boolean addCompany(String adminCode, String companyName,
			String category, Long originalPrice, Integer stockAmount,
			Double incRate) {

		if (!adminCode.equals(Constant.companyAdminCode))
			return false;

		if (Company.get(companyName) != null)
			return false;

		Long openPrice = expert.evaluation(originalPrice * stockAmount,
				stockAmount, incRate, rumor.getCategoryRatio(2, category));
		Integer stockID = status.addStock(Constant.statusAdminCode,
				companyName, category, openPrice);
		if (stockID == null)
			return false;

		// set up account
		String bankCode = bank.open(companyName);
		String stockCode = stockMarket.open(companyName);

		if (!bank.setMoney(Constant.bankAdminCode, companyName, originalPrice
				* stockAmount)) {
			System.out.println("set money market error!");
			return false;
		}

		// if (! stockMarket.setCompanyStock(Constant.marketAdminCode,
		// companyName, stockID, stockAmount))
		// return false;
		if (!stockMarket.addMarketStock(Constant.marketAdminCode, stockID,
				stockAmount)) {
			System.out.println("add stock market error!");
			return false;
		}

		if (!stockMarket.requestSell("market", "market", stockID, openPrice,
				stockAmount)) {
			System.out.println("request sell market error!");
			return false;
		}

		Company newCompany = new Company(companyName, bankCode, stockCode,
				category, incRate, stockID, stockAmount);
		newCompany.insert();

		System.out.println("insert ok");

		return rumor.updateRatio(Constant.rumorAdminCode, companyName, incRate);
	}

	@Override
	public Boolean deleteCompany(String adminCode, String companyName) {
		if (!adminCode.equals(Constant.companyAdminCode))
			return false;

		Company comp = Company.get(companyName);

		if (comp == null)
			return false;

		bank.close(companyName, comp.getBankCode());
		status.delStock(Constant.statusAdminCode, comp.getStockID());
		stockMarket.close(companyName, comp.getStockCode());

		return comp.delete();
	}

	@Override
	public Boolean divideBonus() {
		Company[] compList = Company.getAll();

		for (int i = 0; i < compList.length; i++) {
			long cap = bank.getBalance(compList[i].getCompanyName(),
					compList[i].getBankCode());
			long add = (long) (cap * compList[i].getIncRate());
			bank.setMoney(Constant.bankAdminCode, compList[i].getCompanyName(),
					cap + add);

			// divdie half
			add /= 2;

			String[] stockOwnerList = stockMarket.getStockOwner(
					Constant.marketAdminCode, compList[i].getStockID());
			Integer[] stockAmountList = new Integer[stockOwnerList.length];
			int total = 0;
			for (int p = 0; p < stockOwnerList.length; p++) {
				stockAmountList[p] = stockMarket.getStockAmountByAdmin(
						Constant.marketAdminCode, stockOwnerList[p],
						compList[i].getStockID());
				total += stockAmountList[p];
			}

			if (total > 0) {
				for (int p = 0; p < stockOwnerList.length; p++) {
					long divAmount = add * stockAmountList[p] / total;
					bank.transfer(stockOwnerList[p], bank.cash(compList[i]
							.getCompanyName(), compList[i].getBankCode(),
							divAmount), divAmount);
				}
			}

			rumor.updateRatio(Constant.rumorAdminCode, compList[i]
					.getCompanyName(), compList[i].getIncRate());
		}

		return true;
	}

	@Override
	public Long getCapital(Integer stockID) {
		Company comp = Company.get(stockID);
		if (comp == null)
			return null;
		return bank.getBalance(comp.getCompanyName(), comp.getBankCode());
	}

	/*
	 * @Override public Boolean rumorEffectCategory(String category, Double
	 * effectRatio) { Boolean ret = true; Company[] compList =
	 * Company.getCategory(category); for (int i = 0; i < compList.length; i++)
	 * { compList[i].setIncRate( compList[i].getIncRate() + effectRatio ); if
	 * (!compList[i].update()) ret = false; } return ret; }
	 */

	@Override
	public Boolean rumorEffectCompany(String company, Double effectRatio) {
		Company c = Company.get(company);
		if (c == null)
			return null;
		c.setIncRate(c.getIncRate() + effectRatio);
		return c.update();
	}

	@Override
	public String getCategory(String companyName) {
		Company c = Company.get(companyName);
		if (c == null)
			return null;
		return c.getCategory();
	}

	@Override
	public String[] getCompanyList(String adminCode) {
		Company[] compList = Company.getAll();
		String[] compNameList = new String[compList.length];
		for (int i = 0; i < compList.length; i++)
			compNameList[i] = compList[i].getCompanyName();
		return compNameList;
	}

	@Override
	public Double getIncRate(String adminCode, String companyName) {
		if (!adminCode.equals(Constant.companyAdminCode))
			return null;
		Company c = Company.get(companyName);
		if (c == null)
			return null;
		return c.getIncRate();
	}

	@Override
	public Integer getIssueSize(Integer stockID) {
		Company c = Company.get(stockID);
		if (c == null)
			return null;
		return c.getIssueSize();
	}

	@Override
	public Integer getStockID(String companyName) {
		Company c = Company.get(companyName);
		if (c == null)
			return null;
		return c.getStockID();
	}

}
